我們在認識 CSS Box Model 的時候,有一個必須要知道的屬性,就是 box-sizing
。
我們來看看這個 Box Model:
我們在初學 CSS 的時候,會開始學習一些容易掌握的屬性,例如 width
、height
就是其中幾個。但是,我們剛接觸這兩個屬性的時候,我們不太容易仔細去思考,到底這個 width
跟 height
是指哪裡?
舉個例子,我們看看下面這個方形:
如果我告訴你他是一個 200x200
的方形,你不會覺得有什麼奇怪的地方:
.square {
width: 200px;
height: 200px;
background: #1F7A8C;
}
但是如果是這樣呢:
他一樣是一個 200x200
的方形,只是我們給他一個較寬的 border:
.square {
width: 200px;
height: 200px;
background: #1F7A8C;
border: 10px solid #BFDBF7;
}
問題出來了,請問,200x200
指的是最外圍「包含」 border 的地方,還是內部「不包含」 border 的地方?
這樣的問題,就是 box-sizing
這個屬性要去定義的。
初接觸網頁設計的入門者,會比較容易忽略這個屬性,因而導致有時候出現一些難以理解的狀況。甚至我們可能會不知所措而到最後只能用奇怪的方式解決問題。
例如我們來看下面這個 Table 元件,他每一行的高度是 56.5px
:
假設今天有一個情境,我們需要按照設計師的指示來讓這一行變成 60px
的高度,我們會怎麼做呢?很直覺的反應,我們可能會這樣做:
.table-cell {
height: 60px;
}
就是直接對他指定高度,結果沒想到,我們卻得到這樣的結果:
奇怪?明明原本是 56.6px
,然後我在 CSS 指定他 height: 60px;
,但是最後的結果居然是 92.5px
!?這不是見鬼了嗎?
所以,下一個想法,你可能會覺得可能有哪裡的 CSS 權限太高,碾壓過你目前的權限,此時你會為他加入 !important
來提升 CSS 效果的權限:
.table-cell {
height: 60px !important;
}
結果你會發現,沒有任何變化....
到這時你已經反覆嘗試過各種方法,發現都走投無路了,你只好寫出下面這種 code:
.table-cell {
height: calc(60px - 32.5px);
}
透過這種方式,你真的能夠成功的把這一行的高度變成很精準的 60px
,但是你很不甘心,因為有一行奇怪的 code 不得不在那裡,而且以後的工程師看到這一行,絕對會覺得莫名奇妙,然後你沒有辦法解釋為什麼你要這樣寫。
一樣以 Table 來舉例,不知道有沒有遇過這種情境,有時候我們的 Table 會出現一個令人難以理解的滾動條:
.table-container {
max-width: 800px;
}
.table {
width: 100%;
border: 1px solid #C9C9C9;
overflow-y: auto;
}
<div class="table-container">
<table class="table">...</table>
</div>
明明這個 container 已經限制是 800px
的寬度,然後內部的 table 寬度是 width: 100%;
,我明明沒有設定 X 軸方向的滾動條 overflow-x: scroll;
,但不知道為什麼這個滾動條一直都去不掉,而且右邊的 border 會一直超出範圍。
最慘和最醜的是,當寬度空間不夠時,會出現兩條滾動條:
所以,一樣的,你很有可能透過下面這樣的方式來解決問題:
.table {
width: calc(100% - 2px);
border: 1px solid #C9C9C9;
overflow-y: auto;
}
你會一直搞不懂為什麼你要無來由的去減掉 2px
才能夠去掉那個惱人又無用的滾動條。
事實上,上面這兩個舉例都考驗著我們對於 box-sizing
的理解。
box-sizing
是用來決定物件 width
與 height
的計算方式。白話來說,就是我要以哪裡為測量基準來丈量物件的長寬。主要作用的值有下面兩個:
以上述的範例來說明,在「Table Row 的高度」範例中,我們指定 table row 的高度是 60px
,是在 box-sizing: content-box;
的設置之下,因為他是預設值,所以我們指的 60px
是「不包含」padding
的高度,所以,畫面上面顯示的 92.5px
是我們指定的 60px
再加上 padding
的高度。此時的解決辦法,就是我們將 box-sizing
設置為 border-box
就可以了:
.table-cell {
height: calc(60px - 32.5px);
box-sizing: border-box;
}
同樣的原理,在「不知從何冒出來的滾動條」範例中,會無來由多出來的 2px
,其實是 border 的寬度。我們作個實驗就可以知道,把 border 去掉,這個滾動條就消失了:
.table {
width: calc(100% - 2px);
/* border: 1px solid #C9C9C9; */
overflow-y: auto;
}
所以,在想要保留 border 的前提下,如果我們不用 width: calc(100% - 2px);
,來解決問題,好的方法應該也是去改變 box-sizing 的設置,改為:
.table {
width: 100%;
border: 1px solid #C9C9C9;
overflow-y: auto;
box-sizing: border-box;
}
這樣,我們在計算 width
的時候,就會包含 border 的寬度,而不會出現不知名的滾動條了。
box-sizing
其實是一個簡單的設置而已,但是這個屬性在對 CSS 不熟的階段會很容易被忽略,因為他不像是 background-color
, color
這種屬性,設置了之後會有明顯的顏色改變,而且從名稱上來看也很容易理解。看到 box-sizing
的第一眼,其實我們也不太知道他是作什麼用的,但事實上,他在我們 Box Model 當中非常的重要,可以說是決定基準的角色,為什麼有人可以切版做到 pixel perfect,新手就不行?其實有時候就差在這一個簡單的觀念而已,只要掌握他,你也可以做到 pixel perfect。